import json
from datetime import datetime

from flask import Blueprint, render_template, current_app, request, jsonify
from sqlalchemy import text

from applications.common.curd import model_to_dicts
from applications.common.helper import ModelFilter
from applications.common.utils.validate import xss_escape
from applications.extensions import db
from applications.models import AdminLog, EvalutionReferenceMen
from applications.common.utils.http import table_api, fail_api, success_api
from applications.models import CourseInfoMen, PoliceModels, PsychologyResult
from applications.schemas import CourseInfoMenSchema, PsychologyResultSchema
from applications.schemas.key_frame import EvalutionReferenceMenSchema

course_psychology_bp = Blueprint('coursePsychology', __name__, url_prefix='/course/psychology')


@course_psychology_bp.get('/')
def main():
    return render_template('admin/course/psychology/main.html')


@course_psychology_bp.get('/data')
def data():
    # 获取请求参数
    course_name = xss_escape(request.args.get('course_name', type=str))
    course_type = xss_escape(request.args.get('course_type', type=str))

    # 查询参数构造
    mf = ModelFilter()
    if course_name:
        mf.contains(field_name="course_name", value=course_name)
    if course_type:
        mf.contains(field_name="course_type", value=course_type)
    # orm查询
    # 使用分页获取data需要.items
    course = CourseInfoMen.query.filter(mf.get_filter(model=CourseInfoMen)).with_entities(CourseInfoMen.course_id,
                                                                                          CourseInfoMen.course_name,
                                                                                          CourseInfoMen.course_detail,
                                                                                          CourseInfoMen.course_type).layui_paginate()

    count = course.total
    data = model_to_dicts(schema=CourseInfoMenSchema, data=course.items)
    for d in data:
        d.update(json.loads(d['course_detail'].replace('\'', '\"')))
    # 返回api
    return table_api(data=data, count=count)


@course_psychology_bp.get('/add')
def getPsychologyList():
    return render_template('admin/course/psychology/add.html')


@course_psychology_bp.get('/cover')
def getPsychologyAddCover():
    return render_template('admin/course/psychology/cover.html')


@course_psychology_bp.post('/add')
def submitAdd():
    try:
        course = request.json
        course_details = json.dumps(
            {
                'course_details': course['course_description'],
                'person_gender': course['detail_gender'],
                'person_age': course['detail_age'],
                'person_mind': course['detail_mind'],
                'person_crime_types': course['detail_crime_type'],
                'person_tend': course['detail_tend'],
                'person_emotion': course['detail_emotion']
            },
            ensure_ascii=False
        )
        course_name = course['course_name'],
        course_detail = course_details,
        course_type = course['course_type'],
        video_path = course['video_path'],
        icon_path = str(course['course_icon'])
    except:
        return fail_api(msg="课程参数缺失，请检查参数")

    # 根据图片url找到本地图片，打开为二进制文件
    try:
        with open('.' + icon_path.replace('_uploads/icons', current_app.config.get("UPLOADED_ICONS_DEST")), 'rb') as f:
            image_data = f.read()
    except FileNotFoundError:
        return fail_api(msg="课程封面不存在")

    courseInfo = CourseInfoMen(
        course_name=course_name,
        course_icon=image_data,
        course_detail=course_details,
        course_type=course_type,
        video_path=video_path,
        icon_path=icon_path
    )
    try:
        db.session.add(courseInfo)
        db.session.commit()
    except:
        return fail_api(msg="课程上传失败")
    res = {
        "msg": "上传成功",
        "code": 0,
        "success": True,
        "data":
            {"course_id": courseInfo.course_id}
    }
    return jsonify(res)


@course_psychology_bp.post('/keypoint')
def submitKeypoint():
    try:
        data = request.json
        course_id = data['course_id']
        keypoints = data['key_points']
        emotion_dict = {'积极': 'Pos', '消极': 'Neg', '平静': 'Neutral'}
        for key_point in keypoints:
            evalutionReferenceMen = EvalutionReferenceMen(
                course_id=course_id,
                evaluation_id=int(key_point['id']),
                evalution_period_start_time=time_to_seconds(key_point['start']),
                evalution_period_end_time=time_to_seconds(key_point['end']),
                reference=emotion_dict[key_point['emotion']]
            )
            db.session.add(evalutionReferenceMen)
    except:
        return fail_api(msg="已创建课程，关键帧参数错误，关键帧创建失败，请到编辑页面重新创建关键帧")
    try:
        db.session.commit()
    except:
        return fail_api(msg="关键帧新增失败")
    return success_api(msg="新增关键帧成功")


@course_psychology_bp.get('/edit/<int:course_id>')
def getEditPage(course_id):
    courseInfoMen = CourseInfoMen.query.filter_by(course_id=course_id).with_entities(CourseInfoMen.course_id,
                                                                                     CourseInfoMen.course_name,
                                                                                     CourseInfoMen.course_detail,
                                                                                     CourseInfoMen.course_type,
                                                                                     CourseInfoMen.video_path,
                                                                                     CourseInfoMen.icon_path).one_or_none()
    if not courseInfoMen:
        return fail_api(msg='找不到课程信息')
    keypoints = model_to_dicts(schema=EvalutionReferenceMenSchema,
                               data=EvalutionReferenceMen.query.filter_by(course_id=course_id).all())
    emotion_dict = {'Pos': '积极', 'Neg': '消极', 'Neutral': '平静'}
    for keypoint in keypoints:
        if keypoint['reference'] in emotion_dict:
            keypoint['reference'] = emotion_dict.get(keypoint['reference'])
    courseInfoMenSchema = CourseInfoMenSchema()
    course_data = courseInfoMenSchema.dump(courseInfoMen)
    details = json.loads(course_data['course_detail'].replace('\'', '\"'))
    course_data.update(details)
    course_data['course_type'] = get_value_by_text('course_type', course_data['course_type'])
    course_data['detail_gender'] = get_value_by_text('detail_gender', details['person_gender'])
    course_data['detail_crime_type'] = get_value_by_text('detail_crime_type', details['person_crime_types'])
    course_data['detail_age'] = get_value_by_text('detail_age', details['person_age'])
    course_data['detail_tend'] = get_value_by_text('detail_tend', details['person_tend'])
    course_data['detail_mind'] = get_value_by_text('detail_mind', details['person_mind'])
    course_data['detail_emotion'] = get_value_by_text('detail_emotion', details['person_emotion'])
    return render_template('admin/course/psychology/edit.html', courseInfoMen=course_data, keypoints=keypoints)


@course_psychology_bp.post('/edit')
def saveEdit():
    try:
        data = request.json
        course = data['courseInfoMen']
        keypoints = data['keypoints']
        deletedPoints = data['deletedPoints']
        course_id = course['course_id']
        course_name = course['course_name']
        course_type = course['course_type']
        video_path = course['video_path']
        icon_path = str(course['course_icon'])
        course_details = json.dumps(
            {
                'course_details': course['course_description'],
                'person_gender': course['detail_gender'],
                'person_age': course['detail_age'],
                'person_mind': course['detail_mind'],
                'person_crime_types': course['detail_crime_type'],
                'person_tend': course['detail_tend'],
                'person_emotion': course['detail_emotion']
            },
            ensure_ascii=False
        )
    except:
        return fail_api(msg="参数错误，更新失败")
    courseInfoMen = CourseInfoMen.query.filter_by(course_id=course_id).one_or_none()
    if not courseInfoMen:
        return fail_api(msg="找不到课程信息")
    if not courseInfoMen.icon_path == course['course_icon']:
        try:
            with open('.' + icon_path.replace('_uploads/icons', current_app.config.get("UPLOADED_ICONS_DEST")),
                      'rb') as f:
                image_data = f.read()
                courseInfoMen.course_icon = image_data
                courseInfoMen.icon_path = course['course_icon']
        except FileNotFoundError:
            return fail_api(msg="课程封面不存在")
    courseInfoMen.course_name = course_name
    courseInfoMen.course_detail = course_details
    courseInfoMen.course_type = course_type
    courseInfoMen.video_path = video_path

    # 删除被删除的关键帧
    deletedKeypoints = EvalutionReferenceMen.query.filter(
        EvalutionReferenceMen.evalution_index.in_(deletedPoints)).all()
    for point in deletedKeypoints:
        db.session.delete(point)

    # 更新关键帧及插入关键帧
    keypointList = EvalutionReferenceMen.query.filter_by(course_id=course_id).all()
    try:
        position = 0
        emotion_dict = {'积极': 'Pos', '消极': 'Neg', '平静': 'Neutral'}
        for point in keypoints:
            if 'evalution_index' in point:
                for p in keypointList:
                    if p.evalution_index == point['evalution_index']:
                        p.evaluation_id = position
                        p.evalution_period_start_time = time_to_seconds(point['start'])
                        p.evalution_period_end_time = time_to_seconds(point['end'])
                        p.reference = emotion_dict[point['emotion']]
                        break
            else:
                evalutionReference = EvalutionReferenceMen(course_id=course['course_id'],
                                                           evaluation_id=position,
                                                           evalution_period_start_time=time_to_seconds(point['start']),
                                                           evalution_period_end_time=time_to_seconds(point['end']),
                                                           reference=emotion_dict[point['emotion']])
                db.session.add(evalutionReference)
            position = position + 1
    except KeyError:
        return fail_api(msg="关键帧缺失参数，更新失败")
    try:
        db.session.commit()
    except:
        return fail_api(msg="更新失败")
    return success_api(msg="修改成功")


@course_psychology_bp.get('/result')
def getResultPage():
    return render_template('admin/course/psychology/result.html')


@course_psychology_bp.get('/result/detail/<int:user_id>')
def result_details(user_id):

    results = PsychologyResult.query.order_by('user_date').filter_by(user_id=user_id).layui_paginate()
    results_dict = model_to_dicts(schema=PsychologyResultSchema, data=results.items)
    count = results.total
    return render_template('admin/course/psychology/result_detail.html', data=results_dict, count=count)


@course_psychology_bp.get('/result/detail/detail/<int:id>')
def result_detail_details(id):
    result = PsychologyResult.query.filter_by(id=id).one_or_none()
    if result is None:
        return fail_api(msg="找不到该动作信息！")
    police = PoliceModels.query.filter_by(id=result.user_id).one_or_none()
    psychologyresult = PsychologyResult.query.filter_by(id=id).with_entities(PsychologyResult.id,
                                                                             PsychologyResult.user_id,
                                                                             PsychologyResult.username,
                                                                             PsychologyResult.user_course_types,
                                                                             PsychologyResult.user_course_names,
                                                                             PsychologyResult.user_course_details,
                                                                             PsychologyResult.user_date,
                                                                             PsychologyResult.user_grade, ).one_or_none()
    if not psychologyresult:
        return fail_api(msg='找不到课程信息')

    psychologyresultSchema = PsychologyResultSchema()
    course_data = psychologyresultSchema.dump(psychologyresult)
    details = json.loads(course_data['user_course_details'].replace('\'', '\"'))
    course_data.update(details)
    course_data['detail_gender'] = get_value_by_text('detail_gender', details['person_gender'])
    course_data['details'] = get_value_by_text('details', details['course_details'])
    course_data['detail_crime_type'] = get_value_by_text('detail_crime_type', details['person_crime_types'])
    course_data['detail_age'] = get_value_by_text('detail_age', details['person_age'])
    course_data['detail_tend'] = get_value_by_text('detail_tend', details['person_tend'])
    course_data['detail_mind'] = get_value_by_text('detail_mind', details['person_mind'])
    course_data['detail_emotion'] = get_value_by_text('detail_emotion', details['person_emotion'])
    return render_template('admin/course/psychology/result_detail_detail.html',
                           result=course_data,
                           police=police)


@course_psychology_bp.delete('/remove/<int:course_id>')
def deleteOne(course_id):
    courseInfoMen = CourseInfoMen.query.filter_by(course_id=course_id).delete()
    if not courseInfoMen:
        return fail_api("找不到该课程")
    keypoints = EvalutionReferenceMen.query.filter_by(course_id=course_id).all()
    for keypoint in keypoints:
        db.session.delete(keypoint)
    db.session.commit()
    return success_api("删除成功")


@course_psychology_bp.delete('/batchRemove')
def batchRemove():
    ids = list(map(int, request.form.getlist('ids[]')))
    # 由于使用SQLAlchemy的删除方法，必须要把被删除的数据传输到服务器端，图片二进制传输过慢，因此使用直接执行sql命令的形式
    stmt = text("DELETE FROM course_info_men WHERE course_id IN :ids")
    db.session.execute(stmt, params={"ids": ids})
    keypoints = EvalutionReferenceMen.query.filter(EvalutionReferenceMen.course_id.in_(ids)).all()
    for keypoint in keypoints:
        db.session.delete(keypoint)
    db.session.commit()
    return success_api(msg="删除成功")


def time_to_seconds(time_str):
    time_str = time_str.replace(' ', '')
    time_obj = datetime.strptime(time_str, '%H:%M:%S')
    seconds = (time_obj - datetime(1900, 1, 1)).total_seconds()
    return seconds


def get_text_by_value(id, value):
    option_dict = {
        "detail_gender": {
            "1": "男性",
            "2": "女性"
        },
        "detail_crime_type": {
            "1": "经济犯",
            "2": "财产犯",
            "3": "暴力犯",
            "4": "其他类型犯罪"
        },
        "detail_age": {
            "1": "老年",
            "2": "壮年",
            "3": "青年",
            "4": "少年"
        },
        "detail_tend": {
            "1": "惯犯",
            "2": "偶犯"
        },
        "detail_mind": {
            "1": "常态犯",
            "2": "异常犯"
        },
        "detail_emotion": {
            "1": "激情犯",
            "2": "预谋犯"
        }
    }

    if id in option_dict:
        if value in option_dict[id]:
            return option_dict[id][value]
        else:
            return "Invalid value"
    else:
        return "Invalid id"


# 根据选项的text获得选项的value
def get_value_by_text(id, text):
    option_dict = {
        "course_type": {
            "诱导积极心理": "1",
            "维持平静心理": "2",
            "产生消极心理": "3"
        },
        "detail_gender": {
            "男性": "1",
            "女性": "2"
        },
        "detail_crime_type": {
            "经济犯": "1",
            "财产犯": "2",
            "暴力犯": "3",
            "其他类型犯罪": "4"
        },
        "detail_age": {
            "老年": "1",
            "壮年": "2",
            "青年": "3",
            "少年": "4"
        },
        "detail_tend": {
            "惯犯": "1",
            "偶犯": "2"
        },
        "detail_mind": {
            "常态犯": "1",
            "异常犯": "2"
        },
        "detail_emotion": {
            "激情犯": "1",
            "预谋犯": "2"
        }
    }

    if id in option_dict:
        if text in option_dict[id]:
            return option_dict[id][text]
        else:
            return "0"
    else:
        return "0"
